#include <DHT.h>                  // 使用官方 DHT 库
#include <SoftwareSerial.h>

// 引脚定义
#define DHTPIN PB12               // DHT11 引脚
#define DHTTYPE DHT11             // 指定传感器类型为 DHT11
DHT dht(DHTPIN, DHTTYPE);        // 创建 DHT 对象

const int IA = PB14;              // 电机IA口
const int IB = PB13;              // 电机IB口
const int buzzer = PB9;           // 蜂鸣器
const int SW = PA0;               // 开关风扇按钮
const int modeSW = PC13;          // 模式切换按钮

// 状态变量
bool fanMode = 0;                 // 0=开关控制模式，1=温度阈值控制模式
byte fanNow = 0;                  // 风扇状态：0=关，1=正转，2=反转
bool isChange = false;            // 是否有变化需要执行操作
int boundary = 20;                // 温度阈值
byte speed1 = 255;                // L9110转速设为255
String str = "";                  // 接收串口信息用

// 缓存上一次有效读数（防抖动）
float lastHumidity = 0.0f;
float lastTemperature = 0.0f;

// 串口通信
SoftwareSerial mySerial(PA10, PA9);  // RX, TX（调试用）
SoftwareSerial wifi(PB11, PB10);     // WiFi通信串口

// 定时器变量
unsigned long lastSendTime = 0UL;    // 上次发送时间
const long sendInterval = 3000UL;    // 发送间隔（单位：毫秒）

void setup() {
  mySerial.begin(9600);
  wifi.begin(9600);

  pinMode(IA, OUTPUT);
  pinMode(IB, OUTPUT);
  pinMode(SW, INPUT_PULLUP);      // 推荐使用内部上拉
  pinMode(buzzer, OUTPUT);
  digitalWrite(buzzer, HIGH);     // 初始关闭蜂鸣器

  attachInterrupt(digitalPinToInterrupt(SW), changeSW, RISING);
  attachInterrupt(digitalPinToInterrupt(modeSW), changeModeSW, RISING);

  dht.begin();                    // 初始化 DHT 传感器
  wifi.listen();
}

void loop() {
  static unsigned long lastReadTime = 0;

  // === 每秒读取一次温湿度 ===
  if (millis() - lastReadTime >= 1000UL) {
    float h = dht.readHumidity();
    float t = dht.readTemperature();

    if (!isnan(h) && !isnan(t)) {
      if (h > 100.0f) h = 100.0f;         // 修正湿度上限
      lastHumidity = h;
      lastTemperature = t;
    } else {
      mySerial.println("读取 DHT 数据失败");
    }

    lastReadTime = millis();
  }

  // === 每隔3秒发送一次温湿度给 ESP8266 ===
  if (millis() - lastSendTime >= sendInterval) {
    String state = "temp:" + String(lastTemperature, 1) + " humid:" + String(lastHumidity, 1);
    wifi.println(state);
    mySerial.print("已发送消息：");
    mySerial.println(state);

    lastSendTime = millis();       // 更新最后发送时间
  }

  // === 温控逻辑 ===
  if (fanMode == 1) {
    if (lastTemperature >= boundary && !fanNow) {
      fanNow = 1;
      isChange = true;
      mySerial.println("温控模式：超过阈值温度——自启动电机");
    } else if (lastTemperature < boundary && fanNow) {
      fanNow = 0;
      isChange = true;
      mySerial.println("温控模式：低于阈值温度——自关闭电机");
    }
  }

  // === 执行电机动作 ===
  if (isChange) {
    if (fanNow == 0) {
      stop();
    } else if (fanNow == 1) {
      forward();
    } else {
      backward();
    }
    isChange = false;
  }

  // === 处理来自 ESP8266 的指令 ===
  if (wifi.available() > 0) {
    while (wifi.available() > 0) {
      delay(10);
      str += char(wifi.read());
    }

    mySerial.print("收到8266的指令为：");
    mySerial.println(str);

    if (str.indexOf("打开") != -1) {
      isChange = true;
      fanNow = 1;
    } else if (str.indexOf("关闭") != -1) {
      isChange = true;
      fanNow = 0;
    } else if (str.indexOf("温度阈值") != -1) {
      isChange = true;
      boundary = str.substring(str.indexOf(":") + 1).toInt();
    } else if (str.indexOf("风速") != -1) {
      isChange = true;
      speed1 = str.substring(str.indexOf(":") + 1).toInt();
    } else if (str.indexOf("模式") != -1) {
      isChange = true;
      fanMode = str.substring(str.indexOf(":") + 1).toInt();
    } else if (str.indexOf("顺时针") != -1) {
      isChange = true;
      fanNow = 1;
    } else if (str.indexOf("逆时针") != -1) {
      isChange = true;
      fanNow = 2;
    }

    str = "";
  }
}

// 开关中断函数
void changeSW() {
  isChange = true;
  fanNow = (fanNow == 0) ? 1 : 0;
}

// 模式切换中断函数
void changeModeSW() {
  isChange = true;
  fanMode = !fanMode;
}

// 逆时针旋转
void backward() {
  analogWrite(IA, speed1);
  analogWrite(IB, 0);
  mySerial.println("风扇逆转");
  digitalWrite(buzzer, LOW);
  delay(50);
  digitalWrite(buzzer, HIGH);
}

// 顺时针旋转
void forward() {
  analogWrite(IA, 0);
  analogWrite(IB, speed1);
  mySerial.println("风扇正转");
  digitalWrite(buzzer, LOW);
  delay(50);
  digitalWrite(buzzer, HIGH);
}

// 停止旋转
void stop() {
  analogWrite(IB, 0);
  analogWrite(IA, 0);
  mySerial.println("风扇停止");
  digitalWrite(buzzer, LOW);
  delay(50);
  digitalWrite(buzzer, HIGH);
}